﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using RemoteScriptingLibrary.Microsoft.Win32;

namespace RemoteScriptingLibrary
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using System.IO;

    using LowLevelGraphics;

    /// <summary>
    /// 
    /// </summary>
    public class ImageTools
    {
        private static int SRCCOPY = 0x00CC0020;
        /// <summary>
        /// Initializes a new instance of the <see cref="ImageTools"/> class.
        /// </summary>
        public ImageTools()
        {

        }

        [DllImport("gdi32.dll")]
        public static extern long BitBlt(IntPtr hdcDest, int xDest, int yDest, int width, int height, IntPtr hdcSrc, int xSrc, int ySrc, int dwRop);

        /// <summary>
        /// Erzeugen von einem Image Objekt von dem übergebenen Control
        /// </summary>
        /// <param name="ctrl">Das Control von dem ein Bild erzeugt werden soll</param>
        /// <returns>Ein Image Object mit dem Bild des Controls</returns>
        public static Image CaptureCtrl(Control ctrl)
        {
            Graphics g = ctrl.CreateGraphics();

            // Ein neues Image mit der grösse des jeweiligen Controls anlegen
            Image newImage = new Bitmap(ctrl.Size.Width, ctrl.Size.Height, g);

            Graphics memoryGraphics = Graphics.FromImage(newImage);
            //Handle holen
            IntPtr src = g.GetHdc();
            IntPtr dest = memoryGraphics.GetHdc();

            // das Handle des Ziels
            // die X Position an der das Bild eingefügt werden soll
            // die Y Position an der das Bild eingefügt werden soll
            // die breite des Bildes
            // die höhe des Bildes
            // das Handle der Quelle
            // die X Position an der das Control liegt
            // die Y Position an der das Control liegt
            // Raster Operation Code an dieser Stelle ist es SRCCOPY
            // Natürlich muß der auf der Seite angegebene Hex wert noch in ein int umgerechnet werden
            // mehr informationen auf http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/_celrfternaryrasteroperations.asp
            BitBlt(dest, 0, 0, ctrl.ClientRectangle.Width, ctrl.ClientRectangle.Height, src, ctrl.Location.X, ctrl.Location.Y, 13369376);

            // Handles wieder Freigeben
            g.ReleaseHdc(dest);
            memoryGraphics.ReleaseHdc(src);

            return newImage;
        }

        ///// <summary>
        ///// Erzeugen von einem Image Objekt von dem übergebenen Control
        ///// </summary>
        ///// <param name="ctrl">Das Control von dem ein Bild erzeugt werden soll</param>
        ///// <returns>Ein Image Object mit dem Bild des Controls</returns>
        //public static Image CaptureCtrl(IntPtr ctrl)
        //{
        //    RemoteScriptingLibrary.Microsoft.Win32.Win32.RECT rect = new RemoteScriptingLibrary.Microsoft.Win32.Win32.RECT();
        //    RemoteScriptingLibrary.Microsoft.Win32.Win32.GetWindowRect(ctrl, out rect);

        //    // Ein neues Image mit der grösse des jeweiligen Controls anlegen
        //    Image newImage = new Bitmap(rect.Width, rect.Height, g);

        //    Graphics memoryGraphics = Graphics.FromImage(newImage);
        //    //Handle holen
        //    IntPtr src = g.GetHdc();
        //    IntPtr dest = memoryGraphics.GetHdc();

        //    // das Handle des Ziels
        //    // die X Position an der das Bild eingefügt werden soll
        //    // die Y Position an der das Bild eingefügt werden soll
        //    // die breite des Bildes
        //    // die höhe des Bildes
        //    // das Handle der Quelle
        //    // die X Position an der das Control liegt
        //    // die Y Position an der das Control liegt
        //    // Raster Operation Code an dieser Stelle ist es SRCCOPY
        //    // Natürlich muß der auf der Seite angegebene Hex wert noch in ein int umgerechnet werden
        //    // mehr informationen auf http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/_celrfternaryrasteroperations.asp
        //    BitBlt(dest, 0, 0, rect.Width, rect.Height, src, rect.Left, rect.Right, 13369376);

        //    // Handles wieder Freigeben
        //    g.ReleaseHdc(dest);
        //    memoryGraphics.ReleaseHdc(src);


        //    return newImage;
        //}

        /// <summary>
        /// Takes the screenshot.
        /// </summary>
        /// <param name="windowTitle">The window title.</param>
        /// <param name="_bCompleteDesktop">if set to <c>true</c> [_b complete desktop].</param>
        /// <returns></returns>
        public static Bitmap TakeScreenshot(string windowTitle, bool _bCompleteDesktop)
        {
            string strScreenShotFileName = null;
            Bitmap screenShot = null;
            IntPtr hWnd = IntPtr.Zero;

            Assembly executingAssembly = Assembly.GetExecutingAssembly();

            strScreenShotFileName = Path.GetDirectoryName(executingAssembly.Location) +
            Path.DirectorySeparatorChar + "ScreenShot.jpeg";
            if (_bCompleteDesktop)
            {
                hWnd = (IntPtr)CGraphics.GetDesktopWindow();
            }
            else
            {
                hWnd = (IntPtr)CGraphics.FindWindow(null, windowTitle);
            }

            screenShot = Get(hWnd, false);

            return screenShot;
        }

        /// <summary>
        /// Gets a Bitmap from h WND.
        /// </summary>
        /// <param name="hWnd">The h WND.</param>
        /// <param name="_bGetOnlyClientArea">if set to <c>true</c> [_b get only client area].</param>
        /// <returns></returns>
        public static Bitmap Get(IntPtr hWnd, bool _bGetOnlyClientArea)
        {
            WINDOWINFO winInfo = new WINDOWINFO();
            bool ret = CGraphics.GetWindowInfo(hWnd, ref winInfo);
            if (!ret)
            {
                return null;
            }

            int height = winInfo.rcWindow.Height;
            int width = winInfo.rcWindow.Width;
            if (height == 0 || width == 0) return null;

            Graphics frmGraphics = Graphics.FromHwnd(hWnd);

            IntPtr hDC = IntPtr.Zero;
            if (_bGetOnlyClientArea)
            {
                hDC = frmGraphics.GetHdc(); //-- gets the client area, no menu bars, etc..
            }
            else
            {
                hDC = CGraphics.GetWindowDC(hWnd); //gets the entire window
            }

            Bitmap tmpBitmap = new Bitmap(width, height, frmGraphics);
            Graphics bmGraphics = Graphics.FromImage(tmpBitmap);
            IntPtr bmHdc = bmGraphics.GetHdc();

            CGraphics.BitBlt(bmHdc, 0, 0, width, height, hDC, 0, 0, CGraphics.TernaryRasterOperations.SRCCOPY);

            bmGraphics.ReleaseHdc(bmHdc);
            CGraphics.ReleaseDC(hWnd, hDC);

            return tmpBitmap;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceX"></param>
        /// <param name="sourceY"></param>
        /// <param name="destX"></param>
        /// <param name="destY"></param>
        /// <param name="regionSize"></param>
        /// <returns></returns>
        public static Image CaptureScreen(int sourceX, int sourceY, int destX, int destY,
            Size regionSize)
        {
            Bitmap bmp = new Bitmap(regionSize.Width, regionSize.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.CopyFromScreen(sourceX, sourceY, destX, destY, regionSize);
            return bmp;
        }

        /// <summary>
        /// Gets the bitmap.
        /// </summary>
        /// <param name="Ctrl">The CTRL.</param>
        /// <returns></returns>
        public static Bitmap GetBitmap(Control Ctrl)
        {

            //  create the source graphics and the required bitmap
            Graphics graphicsControl = Graphics.FromHwnd(Ctrl.Handle);
            Bitmap Result = new Bitmap(Ctrl.Width, Ctrl.Height, graphicsControl);

            //  we need handles to copy graphics
            IntPtr hdcControl = graphicsControl.GetHdc();
            Graphics graphicsDestination = Graphics.FromImage(Result);
            IntPtr hdcDestination = graphicsDestination.GetHdc();

            //    copy the image from source hdcCtrl to destination hdcDest
            //  using BitBlt (bit block transfer) of Windows GDI
            //      a form would normally printed without title or menu bar;
            //      therefore, one has to move the graphics
            int nSourceX = 0;
            int nSourceY = 0;
            if (Ctrl is Form)
            {
                nSourceX = Ctrl.ClientSize.Width - Ctrl.Width + 4;
                nSourceY = Ctrl.ClientSize.Height - Ctrl.Height + 4;
            }
            else
            {
                nSourceX = 0;
                nSourceY = 0;
            }
            BitBlt(hdcDestination, 0, 0, Ctrl.Width, Ctrl.Height, hdcControl, nSourceX, nSourceY, SRCCOPY);

            //    free the used objects
            graphicsControl.ReleaseHdc(hdcControl);
            graphicsDestination.ReleaseHdc(hdcDestination);

            //  that's all work for the bmp using NET 1.1 instructions
            return Result;
        }

        /*  void GenerateTheHistogram(Bitmap bmp)
          {
              if (bmp == null) return;
              Bitmap bmp_binary = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format32bppRgb); //Version 1
              //bmp_binary = new Bitmap( bmp.Width, bmp.Height, PixelFormat.Format32bppRgb ); //Version 2
              //bmp_binary = new Bitmap( bmp.Width, bmp.Height, PixelFormat.Format1bppIndexed ); //Version 3
              Byte[] grayarray = new Byte[bmp.Height, bmp.Width];
              byte[] Histogram;
              Color color;
              for (Int32 y = 0; y < bmp.Height; y++)
                  for (Int32 x = 0; x < bmp.Width; x++)
                  {
                      color = bmp.GetPixel(x, y);
                      Int32 gray = (color.R + color.G + color.B) / 3;
                      grayarray[y, x] = (Byte)gray;
                      Histogram[gray]++;
                  }
              Int32 hmax = 0;
              for (Int32 i = 0; i < 256; i++)
                  if (Histogram[i] > hmax) hmax = Histogram[i];
              for (Int32 i = 0; i < 256; i++)
                  Histogram[i] = (100 * Histogram[i]) / hmax;
              bmp_histo = new Bitmap(histo_r.Width, histo_r.Height, PixelFormat.Format32bppRgb);
              g_histo = Graphics.FromImage(bmp_histo);
              g_histo.FillRectangle(wbrush, 0, 0, 256, 100);
              g_histo.DrawString("click here and move !", Font, bbrush, 1, 1);
              for (Int32 i = 0; i < 256; i++) g_histo.DrawLine(bpen, i, 100, i, 100 - Histogram[i]);
              g_histo.DrawRectangle(rpen, 0, 0, 256, 100);
          }*/
    }
}

